package com.freedy.algorithm.kruskal;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.StringJoiner;

/**
 * @author Freedy
 * @date 2021/4/13 21:50
 */
public class MGraph {
    private final int edgeNum;//节点的个数
    private final char[] data;//存放在节点的数据
    private final int[][] weight;//存放边，就是我们的邻接矩阵
    private final ArrayList<Edge> edges;

    public MGraph(char[] data, int[][] weight) {
        if (data.length != weight.length || weight[0].length != weight.length)
            throw new RuntimeException("传入的数据不匹配!");
        edges = new ArrayList<>();
        for (int i = 0; i < weight.length; i++) {
            for (int j = 0; j < weight[i].length; j++) {
                if (weight[i][j] > 0 && i >= j) {
                    edges.add(new Edge(i,j,data[i],data[j], weight[i][j]));
                }
            }
        }
        this.data = data;
        this.weight = weight;
        edgeNum=edges.size();
        edges.sort(Comparator.comparingInt(Edge::getWeight));
    }

    public void printGraph() {
        for (int i = -1; i < weight.length; i++) {
            for (int j = -1; j < weight[0].length; j++) {
                if (i == -1) {
                    System.out.print(j == -1 ? "   " : data[j] + "   ");
                } else if (j == -1) {
                    System.out.print(data[i] + "  ");
                } else {
                    System.out.print(weight[i][j] + ((weight[i][j] + "").length() == 1 ? "   " : "  "));
                }
            }
            System.out.println();
        }
    }

    /**
     * 求出给定点的终点
     * @param ends 该数组的下标表示第一个点里面的值表示他的下一个点
     *             例如：3的下一个点是2，这时ends[3]就等于2，
     *             以此类推可以得到这个点的终点
     * @param i 给定点的下标
     * @return 终点下标
     */
    public int getEnd(int[] ends,int i){
        while (ends[i]!=0){
            i=ends[i];
        }
        return i;
    }

    //=====================getter======================
    public int getEdgeNum() {
        return edgeNum;
    }

    public char[] getData() {
        return data;
    }

    public int[][] getWeight() {
        return weight;
    }

    public ArrayList<Edge> getEdges() {
        return edges;
    }

    public static class Edge {
        private final int start;
        private final int end;
        private final char startPoint;
        private final char endPoint;
        private final int weight;


        public Edge(int start, int end,char startPoint,char endPoint ,int weight) {
            this.start = start;
            this.end = end;
            this.startPoint=startPoint;
            this.endPoint=endPoint;
            this.weight = weight;
        }

        @Override
        public String toString() {
            return new StringJoiner(", ", Edge.class.getSimpleName() + "[", "]")
                    .add("startPoint=" + startPoint)
                    .add("endPoint=" + endPoint)
                    .add("weight=" + weight)
                    .toString();
        }

        public int getStart() {
            return start;
        }

        public int getEnd() {
            return end;
        }

        public int getWeight() {
            return weight;
        }

        public char getStartPoint() {
            return startPoint;
        }

        public char getEndPoint() {
            return endPoint;
        }

    }
}
